diff options
Diffstat (limited to 'app/[lng]/engineering/(engineering)/system')
6 files changed, 344 insertions, 0 deletions
diff --git a/app/[lng]/engineering/(engineering)/system/admin-users/page.tsx b/app/[lng]/engineering/(engineering)/system/admin-users/page.tsx new file mode 100644 index 00000000..11a9e9fb --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/admin-users/page.tsx @@ -0,0 +1,60 @@ +import * as React from "react" +import { type SearchParams } from "@/types/table" + +import { getValidFilters } from "@/lib/data-table" +import { Skeleton } from "@/components/ui/skeleton" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { DateRangePicker } from "@/components/date-range-picker" +import { Separator } from "@/components/ui/separator" + +import { searchParamsCache } from "@/lib/admin-users/validations" +import { getAllCompanies, getAllRoles, getUserCountGroupByCompany, getUserCountGroupByRole, getUsers } from "@/lib/admin-users/service" +import { AdmUserTable } from "@/lib/admin-users/table/ausers-table" + +interface IndexPageProps { + searchParams: Promise<SearchParams> +} + +export default async function UserTable(props: IndexPageProps) { + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + const validFilters = getValidFilters(search.filters) + + const promises = Promise.all([ + getUsers({ + ...search, + filters: validFilters, + }), + getUserCountGroupByCompany(), + getUserCountGroupByRole(), + getAllCompanies(), + getAllRoles() + ]) + + return ( + <React.Suspense + fallback={ + <DataTableSkeleton + columnCount={6} + searchableColumnCount={1} + filterableColumnCount={2} + cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]} + shrinkZero + /> + } + > + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">Vendor Admin User Management</h3> + <p className="text-sm text-muted-foreground"> + 협력업체의 유저 전체를 조회하고 어드민 유저를 생성할 수 있는 페이지입니다. 이곳에서 초기 유저를 생성시킬 수 있습니다. <br />생성 후에는 생성된 사용자의 이메일로 생성 통보 이메일이 발송되며 사용자는 이메일과 OTP로 로그인이 가능합니다. + </p> + </div> + <Separator /> + <AdmUserTable promises={promises} /> + </div> + </React.Suspense> + + ) +} diff --git a/app/[lng]/engineering/(engineering)/system/layout.tsx b/app/[lng]/engineering/(engineering)/system/layout.tsx new file mode 100644 index 00000000..7e8f69d0 --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/layout.tsx @@ -0,0 +1,80 @@ +import { Metadata } from "next" + +import { Separator } from "@/components/ui/separator" +import { SidebarNav } from "@/components/layout/sidebar-nav" + +export const metadata: Metadata = { + title: "System Setting", + // description: "Advanced form example using react-hook-form and Zod.", +} + + +interface SettingsLayoutProps { + children: React.ReactNode + params: { lng: string } +} + +export default async function SettingsLayout({ + children, + params, +}: { + children: React.ReactNode + params: { lng: string } +}) { + const resolvedParams = await params + const lng = resolvedParams.lng + + + const sidebarNavItems = [ + + { + title: "삼성중공업 사용자", + href: `/${lng}/evcp/system`, + }, + { + title: "Roles", + href: `/${lng}/evcp/system/roles`, + }, + { + title: "권한 통제", + href: `/${lng}/evcp/system/permissions`, + }, + { + title: "협력업체 사용자", + href: `/${lng}/evcp/system/admin-users`, + }, + + { + title: "비밀번호 정책", + href: `/${lng}/evcp/system/password-policy`, + }, + + ] + + + return ( + <> + <div className="container py-6"> + <section className="overflow-hidden rounded-[0.5rem] border bg-background shadow"> + <div className="hidden space-y-6 p-10 pb-16 md:block"> + <div className="space-y-0.5"> + <h2 className="text-2xl font-bold tracking-tight">시스템 설정</h2> + <p className="text-muted-foreground"> + 사용자, 롤, 접근 권한을 관리하세요. + </p> + </div> + <Separator className="my-6" /> + <div className="flex flex-col space-y-8 lg:flex-row lg:space-x-12 lg:space-y-0"> + <aside className="-mx-4 lg:w-1/5"> + <SidebarNav items={sidebarNavItems} /> + </aside> + <div className="flex-1 ">{children}</div> + </div> + </div> + </section> + </div> + + + </> + ) +} diff --git a/app/[lng]/engineering/(engineering)/system/page.tsx b/app/[lng]/engineering/(engineering)/system/page.tsx new file mode 100644 index 00000000..fe0a262c --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/page.tsx @@ -0,0 +1,56 @@ +import { Separator } from "@/components/ui/separator" +import { type SearchParams } from "@/types/table" +import * as React from "react" +import { getValidFilters } from "@/lib/data-table" +import { searchParamsCache } from "@/lib/admin-users/validations" +import { getAllRoles, getUsersEVCP } from "@/lib/users/service" +import { getUserCountGroupByRole } from "@/lib/admin-users/service" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { UserTable } from "@/lib/users/table/users-table" + +interface IndexPageProps { + searchParams: Promise<SearchParams> +} + +export default async function SystemUserPage(props: IndexPageProps) { + + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + + const validFilters = getValidFilters(search.filters) + + const promises = Promise.all([ + getUsersEVCP({ + ...search, + filters: validFilters, + }), + getUserCountGroupByRole(), + getAllRoles() + ]) + + return ( + <React.Suspense + fallback={ + <DataTableSkeleton + columnCount={6} + searchableColumnCount={1} + filterableColumnCount={2} + cellWidths={["10rem", "12rem", "12rem", "12rem"]} + shrinkZero + /> + } + > + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">SHI Users</h3> + <p className="text-sm text-muted-foreground"> + 시스템 전체 사용자들을 조회하고 관리할 수 있는 페이지입니다. 사용자에게 롤을 할당하는 것으로 메뉴별 권한을 관리할 수 있습니다. + </p> + </div> + <Separator /> + <UserTable promises={promises} /> + </div> + </React.Suspense> + + ) +}
\ No newline at end of file diff --git a/app/[lng]/engineering/(engineering)/system/password-policy/page.tsx b/app/[lng]/engineering/(engineering)/system/password-policy/page.tsx new file mode 100644 index 00000000..0f14fefe --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/password-policy/page.tsx @@ -0,0 +1,63 @@ +// app/admin/password-policy/page.tsx + +import * as React from "react" +import { Skeleton } from "@/components/ui/skeleton" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Separator } from "@/components/ui/separator" +import { Alert, AlertDescription } from "@/components/ui/alert" +import { AlertTriangle } from "lucide-react" +import SecuritySettingsTable from "@/components/system/passwordPolicy" +import { getSecuritySettings } from "@/lib/password-policy/service" + + +export default async function PasswordPolicyPage() { + try { + // 보안 설정 데이터 로드 + const securitySettings = await getSecuritySettings() + + return ( + <React.Suspense + fallback={ + <DataTableSkeleton + columnCount={4} + searchableColumnCount={0} + filterableColumnCount={0} + cellWidths={["20rem", "30rem", "15rem", "10rem"]} + shrinkZero + /> + } + > + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">협력업체 사용자 비밀번호 정책 설정</h3> + <p className="text-sm text-muted-foreground"> + 협력업체 사용자들을 위한 비밀번호 정책과 보안 설정을 관리할 수 있습니다. + </p> + </div> + <Separator /> + <SecuritySettingsTable initialSettings={securitySettings} /> + </div> + </React.Suspense> + ) + } catch (error) { + console.error('Failed to load security settings:', error) + + return ( + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">협력업체 사용자 비밀번호 정책 설정</h3> + <p className="text-sm text-muted-foreground"> + 협력업체 사용자들을 위한 비밀번호 정책과 보안 설정을 관리할 수 있습니다. + </p> + </div> + <Separator /> + <Alert variant="destructive"> + <AlertTriangle className="h-4 w-4" /> + <AlertDescription> + 보안 설정을 불러오는 중 오류가 발생했습니다. 페이지를 새로고침하거나 관리자에게 문의하세요. + </AlertDescription> + </Alert> + </div> + ) + } +}
\ No newline at end of file diff --git a/app/[lng]/engineering/(engineering)/system/permissions/page.tsx b/app/[lng]/engineering/(engineering)/system/permissions/page.tsx new file mode 100644 index 00000000..6aa2b693 --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/permissions/page.tsx @@ -0,0 +1,17 @@ +import PermissionsTree from "@/components/system/permissionsTree" +import { Separator } from "@/components/ui/separator" + +export default function PermissionsPage() { + return ( + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">Permissions</h3> + <p className="text-sm text-muted-foreground"> + Set permissions to the menu by Role + </p> + </div> + <Separator /> + <PermissionsTree/> + </div> + ) +} diff --git a/app/[lng]/engineering/(engineering)/system/roles/page.tsx b/app/[lng]/engineering/(engineering)/system/roles/page.tsx new file mode 100644 index 00000000..fe074600 --- /dev/null +++ b/app/[lng]/engineering/(engineering)/system/roles/page.tsx @@ -0,0 +1,68 @@ +import * as React from "react" +import { type SearchParams } from "@/types/table" + +import { getValidFilters } from "@/lib/data-table" +import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" +import { Separator } from "@/components/ui/separator" + +import { searchParamsCache } from "@/lib/roles/validations" +import { searchParamsCache as searchParamsCache2 } from "@/lib/admin-users/validations" +import { RolesTable } from "@/lib/roles/table/roles-table" +import { getRolesWithCount } from "@/lib/roles/services" +import { getUsersAll } from "@/lib/users/service" + +interface IndexPageProps { + searchParams: Promise<SearchParams> +} + +export default async function UserTable(props: IndexPageProps) { + const searchParams = await props.searchParams + const search = searchParamsCache.parse(searchParams) + const search2 = searchParamsCache2.parse(searchParams) + + const validFilters = getValidFilters(search.filters) + + const promises = Promise.all([ + getRolesWithCount({ + ...search, + filters: validFilters, + }), + + + ]) + + + const promises2 = Promise.all([ + getUsersAll({ + ...search2, + filters: validFilters, + }, "evcp"), + ]) + + + return ( + <React.Suspense + fallback={ + <DataTableSkeleton + columnCount={6} + searchableColumnCount={1} + filterableColumnCount={2} + cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]} + shrinkZero + /> + } + > + <div className="space-y-6"> + <div> + <h3 className="text-lg font-medium">Role Management</h3> + <p className="text-sm text-muted-foreground"> + 역할을 생성하고 역할에 유저를 할당할 수 있는 페이지입니다. 역할에 메뉴의 접근 권한 역시 할당할 수 있습니다. + </p> + </div> + <Separator /> + <RolesTable promises={promises} promises2={promises2} /> + </div> + </React.Suspense> + + ) +} |
